#ifndef __GENERICSERVER_H__
#define __GENERICSERVER_H__

typedef struct GenServer_t GenServer;

typedef enum ErrGSRun_t
{
    GS_SUCCESS          = 0 ,
    GSERR_SOCKET            ,       /*  Error on opening socket fd                      */
    GSERR_SET_SOCK_OP       ,       /*  Error on setting socket's options               */
    GSERR_LISTEN            ,       /*  Error on listen to connections                  */
    GSERR_BIND              ,       /*  Error bind server socket to connections         */
    GSERR_SELECT            ,       /*  Error during the select loop (ServerRun)        */
    GSERR_RECV              ,       /*  Error while trying recieve message from client  */
    GSERR_SEND              ,       /*  Error while trying sending message to client    */
    GSERR_ACCEPT            ,       /*  Error on acception new client                   */
    GSERR_ALLOCATION        ,       /*  Error on memory allocations                     */
    GSERR_NEW_LIST          ,       /*  Error on creating new list                      */
    GSERR_INSERT_TREE       ,       /*  Error on inserting client to tree               */
    GSERR_INSERT_LIST       ,       /*  Error on inserting IORequest to list            */
    GSERR_CLIENT_NOT_EXIST  ,       /*  Error client not exist in server                */
    GSERR_ADD_UDP_CLIENT
}ErrGSRun;


typedef void* GSKey;

/*  Explanation: All user supplied callback functions gets as parameter void* application, that represent the application saved info.       *
 *  all functions except the header calculate function gets also as parameter GSKey _key, that is the handler represents a specific client.   */

/*  User supplied function for calculating from header the size of data to recieve (without the size of header).            */
typedef size_t (*HeaderCalcFunc)(void* _app, void* _header);
/*  User supplied callback function for accepting new client.                                                               */
typedef void (*NewClientFunc)(void* _app, GSKey _key);
/*  User supplied callback function for responding to new message, gets besides the above specified param also buffer and   *
 *  the size of it(including the header)                                                                                    */
typedef void (*NewMssgFunc)(void* _app, GSKey _key, void* _buffer, size_t _size);
/*  User supplied callback function for responding to exception message.                                                    */
/*typedef void (*NewExcpFunc)(void* _app, GSKey _key, void* _buffer, size_t _size);*/
/*  User supplied callback function for handling a client's disconnection.                                                  */
typedef void (*DisconnectFunc)(void* _app, GSKey _key, size_t _nonRecvBytes, size_t _nonSendBytes);

/*  Create server. get the functions above, port, pointer to application, header size, exception message size.              *
 *  Return value is GenServer pointer on failure 0, and prints to stderr.                                                   *
 *  Failure can appear if allocation failed.                                                                                */
GenServer* GenServerNew(int _port,
                        void* _application,
                        size_t _headerSize,
                        HeaderCalcFunc ,
                        NewClientFunc ,
                        NewMssgFunc,
                        DisconnectFunc);

/*  Run the server. The run function is a loop function that manage new connections, recieves messages from clients and calls the           *
 * callback functions according to the events. On failure return error numbers and prints to stderr.                                        */
int GenServerRun(GenServer* );

/*  Stops the run of server. This function can be called from the user supplied callback functions for stopping the run loop.               */
void GenServerStop(GenServer* );

/*  Drop client ,reconized by key, from the server.                                                                                         */
int GenServerDrop(GenServer* , GSKey _key);

/*  Write to client, recognized by key, from buffer the amount of bytes of _size.                                                           */
int GenServerWrite(GenServer* , GSKey _key, void* _buffer, size_t _size);

void GenServerDel(GenServer* );


/*  Add new scheduleded task to the server. The task to run is _func, with _data for state, and run every period of time given in msec.     *
 *  On succes return 0, on failure -1. Failure can occure on allocation failure.                                                            */
int GenServerSchedAddTask(GenServer*, int(*_func)(void* _data), size_t _period, void* _data);




#endif /* __GENERICSERVER_H__   */
